#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;

class st_tree {
	int cnt = 1, qcnt = 1, root = 0;
	vector<int> head, next, to, vis;
	vector<int> qhead, qnext, qto;

	vector<int> father;

	int find(int x)
	{
		return x == father[x] ? x : father[x] = find(father[x]);
	}

	int merge(int x, int y)
	{
		int fx = find(x);
		int fy = find(y);
		return father[fx] = fy;
	}

	void addedge(int u, int v)
	{
		next[cnt] = head[u];
		to[cnt] = v;
		head[u] = cnt++;
	}

	void addquest(int u, int v)
	{
		qnext[qcnt] = qhead[u];
		qto[qcnt] = v;
		qhead[u] = qcnt++;
	}

	void build(int n, int m)
	{
		for (int i = 0, u, v; i < n - 1; i++) {
			cin >> u >> v;
			addedge(u, v);
			addedge(v, u);
		}

		for (int i = 0, u, v; i < m; i++) {
			cin >> u >> v;
			addquest(u, v);
			addquest(v, u);
		}

		iota(father.begin(), father.end(), 0);
	}

	void dfs(int u, int parent)
	{
		vis[u] = 1;
		for (int e = head[u], v = to[e]; e; e = next[e], v = to[e]) {
			if (v == parent) {
				continue;
			}
			dfs(v, u);

			for (int q = qhead[v], p = qto[q]; q; q = qnext[q], p = qto[q]) {
				if (vis[p]) {
					ans[(q + 1) / 2] = find(p);
				}
			}
			merge(v, u);
		}
	}

	void dfs2(int u, int parent)
	{
		vis[u] = 1;
		for (int e = head[u], v = to[e]; e; e = next[e], v = to[e]) {
			if (v == parent) {
				continue;
			}
			dfs2(v, u);
			father[v] = u;
		}

		for (int q = qhead[u], p = qto[q]; q; q = qnext[q], p = qto[q]) {
			if (vis[p]) {
				ans[(q + 1) / 2] = find(p);
			}
		}
	}

    public:
	vector<int> ans;

	st_tree(int n, int m, int root)
		: vis(n + 1, 0), head(n + 1, 0), next(n << 1, 0), to(n << 1, 0), qhead(m + 1, 0), qnext((m << 1) + 1, 0), qto((m << 1) + 1, 0), ans(m + 1, 0), father(n + 1, 0),
		  root(root)
	{
		build(n, m);
		dfs2(root, root);
	}
};

int main()
{
	int n = 0, m = 0, root = 0;
	cin >> n >> m >> root;
	st_tree stree(n, m, root);
	for (int i = 1; i < stree.ans.size(); i++) {
		cout << stree.ans[i] << '\n';
	}
	return 0;
}
